package com.yds.ydsdatasetbackend.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yds.ydsdatasetbackend.exception.BusinessException;
import com.yds.ydsdatasetbackend.exception.ErrorCode;
import com.yds.ydsdatasetbackend.exception.ThrowUtils;
import com.yds.ydsdatasetbackend.model.dto.patient.PatientAddRequest;
import com.yds.ydsdatasetbackend.model.dto.patient.PatientQueryRequest;
import com.yds.ydsdatasetbackend.model.dto.patient.PatientUpdateRequest;
import com.yds.ydsdatasetbackend.model.entity.*;
import com.yds.ydsdatasetbackend.model.vo.FilePredictVO;
import com.yds.ydsdatasetbackend.model.vo.PatientGroupVO;
import com.yds.ydsdatasetbackend.model.vo.PatientVO;
import com.yds.ydsdatasetbackend.service.FilePredictService;
import com.yds.ydsdatasetbackend.service.PatientGroupService;
import com.yds.ydsdatasetbackend.service.PatientService;
import com.yds.ydsdatasetbackend.mapper.PatientMapper;
import com.yds.ydsdatasetbackend.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author YDS
* @description 针对表【patient(病人表)】的数据库操作Service实现
* @createDate 2025-04-09 15:02:16
*/
@Service
public class PatientServiceImpl extends ServiceImpl<PatientMapper, Patient>
    implements PatientService{

    @Resource
    private FilePredictService filePredictService;

    @Resource
    private UserService userService;

    @Resource
    private PatientGroupService patientGroupService;

    /**
     * 添加病人信息
     * @param patientAddRequest
     * @param request
     * @return
     */
    @Override
    public PatientVO addPatient(PatientAddRequest patientAddRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.PARAMS_ERROR,"用户不存在");
        if(patientAddRequest.getGroupId() == null) patientAddRequest.setGroupId(-1L);
        // 保存文件基本信息
        Patient patient = new Patient();
        BeanUtils.copyProperties(patientAddRequest, patient);
        patient.setUserId(loginUser.getId());
        FilePredictVO filePredictVO = filePredictService.addFilePredict(patientAddRequest.getFilePredictAddRequest(), loginUser);
        patient.setPredictId(filePredictVO.getId());
        boolean save = this.save(patient);
        ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR);

        //返回信息
        PatientVO patientVO = PatientVO.objToVo(patient);
        patientVO.setFilePredictVO(filePredictVO);
        return patientVO;
    }

    @Override
    public PatientVO getPatientVO(Patient patient, HttpServletRequest request) {
        // 对象转封装类
        PatientVO patientVO = PatientVO.objToVo(patient);
        // 关联查询用户信息
        Long predictId = patient.getPredictId();
        if (predictId != null && predictId > 0) {
            FilePredict filePredict = filePredictService.getById(predictId);
            FilePredictVO filePredictVO = filePredictService.getFilePredictVO(filePredict, request);
            patientVO.setFilePredictVO(filePredictVO);
        }
        Long groupId = patient.getGroupId();
        if (groupId != null && groupId > 0) {
            PatientGroup patientGroup = patientGroupService.getById(groupId);
            PatientGroupVO patientGroupVO = PatientGroupVO.objToVo(patientGroup);
            patientVO.setPatientGroupVO(patientGroupVO);
        }
        return patientVO;
    }

    /**
     * 分页获取图片封装,将获取到的页进行脱敏
     */
    @Override
    public Page<PatientVO> getPatientVOPage(Page<Patient> patientPage, HttpServletRequest request) {
        List<Patient> patientList = patientPage.getRecords();
        Page<PatientVO> patientVOPage = new Page<>(patientPage.getCurrent(), patientPage.getSize(), patientPage.getTotal());
        if (CollUtil.isEmpty(patientList)) {
            return patientVOPage;
        }
        // 对象列表 => 封装对象列表
        List<PatientVO> patientVOList = patientList.stream().map(PatientVO::objToVo).collect(Collectors.toList());
        // 1. 关联查询预测信息和分组信息
        Set<Long> filePredictIdSet = patientList.stream().map(Patient::getPredictId).collect(Collectors.toSet());
        Map<Long, List<FilePredict>> filePredictIdListMap = filePredictService.listByIds(filePredictIdSet).stream()
                .collect(Collectors.groupingBy(FilePredict::getId));

        Set<Long> groupIdSet = patientList.stream().map(Patient::getGroupId).collect(Collectors.toSet());
        Map<Long, List<PatientGroup>> patientGroupIdListMap = patientGroupService.listByIds(groupIdSet).stream()
                .collect(Collectors.groupingBy(PatientGroup::getId));

        // 2. 填充信息
        patientVOList.forEach(patientVO -> {
            Long predictId = patientVO.getPredictId();
            Long groupId = patientVO.getGroupId();
            FilePredict filePredict = null;
            PatientGroup patientGroup = null;
            if (filePredictIdListMap.containsKey(predictId)) {
                 filePredict = filePredictIdListMap.get(predictId).get(0);
            }
            if (patientGroupIdListMap.containsKey(groupId)) {
                patientGroup = patientGroupIdListMap.get(groupId).get(0);
            }
            patientVO.setFilePredictVO(filePredictService.getFilePredictVO(filePredict, request));
            patientVO.setPatientGroupVO(PatientGroupVO.objToVo(patientGroup));
        });
        patientVOPage.setRecords(patientVOList);
        return patientVOPage;
    }

    /**
     * 分页获取图片包装
     *
     * @param patientQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<Patient> getQueryWrapper(PatientQueryRequest patientQueryRequest) {
        QueryWrapper<Patient> queryWrapper = new QueryWrapper<>();
        if (patientQueryRequest == null) {
            return queryWrapper;
        }
        // 从对象中取值
        Long id = patientQueryRequest.getId();
        Long predictId = patientQueryRequest.getPredictId();
        Long userId = patientQueryRequest.getUserId();
        Long groupId = patientQueryRequest.getGroupId();
        String patientName = patientQueryRequest.getPatientName();
        String note = patientQueryRequest.getNote();
        Date createTime = patientQueryRequest.getCreateTime();
        Date startCreateTime = patientQueryRequest.getStartCreateTime();
        Date endCreateTime = patientQueryRequest.getEndCreateTime();
        String sortField = patientQueryRequest.getSortField();
        String sortOrder = patientQueryRequest.getSortOrder();



        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjUtil.isNotEmpty(predictId), "predictId", predictId);
        queryWrapper.eq(ObjUtil.isNotEmpty(groupId), "groupId", groupId);
        queryWrapper.like(StrUtil.isNotBlank(patientName), "patientName", patientName);
        queryWrapper.like(StrUtil.isNotBlank(patientName), "patientName", patientName);
        queryWrapper.like(StrUtil.isNotBlank(note), "note", note);
        queryWrapper.ge(ObjUtil.isNotEmpty(startCreateTime), "createTime", startCreateTime);
        queryWrapper.lt(ObjUtil.isNotEmpty(endCreateTime), "createTime", endCreateTime);
        // 排序
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }


    @Override
    public void updatePatient(PatientUpdateRequest patientUpdateRequest, User loginUser) {
        // 在此处将实体类和 DTO 进行转换
        Patient patient = new Patient();
        BeanUtils.copyProperties(patientUpdateRequest, patient);
        // 校验权限
        checkPatientAuth(loginUser, this.getById(patientUpdateRequest.getId()));
        // 设置编辑时间
        patient.setUpdateTime(new Date());
        // 数据校验
        if(StrUtil.isBlank(patient.getPatientName())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "病人名字不可为空");
        }
        // 判断是否存在
        long id = patientUpdateRequest.getId();
        Patient oldPatient = this.getById(id);
        ThrowUtils.throwIf(oldPatient == null, ErrorCode.NOT_FOUND_ERROR);
        // 操作数据库
        boolean result = this.updateById(patient);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
    }


    @Override
    public void checkPatientAuth(User loginUser, Patient patient) {
        Long loginUserId = loginUser.getId();
        if (!loginUserId.equals(patient.getUserId()) && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
    }

}




